/*
 * @Author: Wenjie Zhong
 * @Date: 2021-10-22 09:36:36
 * @LastEditTime: 2022-02-09 16:46:58
 * @LastEditors: Wenjie Zhong
 * @Description: 守护进程通用配置
 * @FilePath: /xpack/src/modules/include/deamon/common.h
 */

#ifndef MODULES_DEAMON_COMMON_H_
#define MODULES_DEAMON_COMMON_H_

#include <string>
#include <list>
#include <map>
#include <string>
#include <stdint.h>
#include <memory>
#include <unistd.h>



//#include "system/system_modules.h"

namespace xag {
namespace xos {
namespace deamon {

//constexpr char KEYWORDS[] = "xag_";kworker
constexpr char KEYWORDS[] = "kworker";

#if 1
#define PKG_NAME "PowerCtl"
const std::string SWITCH_CONFIG_PATH =
    "/usr/app/config/" + std::string(PKG_NAME) + "/deamon_switch.conf";

const std::string MONITOR_REPORT_CONFIG_PATH =
    "/usr/app/config/" + std::string(PKG_NAME) + "/monitor_report.conf";
#endif

/* Files */
#define STAT      "/proc/stat"
#define UPTIME      "/proc/uptime"
#define DISKSTATS    "/proc/diskstats"
#define INTERRUPTS    "/proc/interrupts"
#define MEMINFO      "/proc/meminfo"
#define SYSFS_BLOCK    "/sys/block"
#define SYSFS_DEV_BLOCK    "/sys/dev/block"
#define SYSFS_DEVCPU    "/sys/devices/system/cpu"
#define SYSFS_TIME_IN_STATE  "cpufreq/stats/time_in_state"
#define S_STAT      "stat"
#define DEVMAP_DIR    "/dev/mapper"
#define DEVICES      "/proc/devices"
#define SYSFS_USBDEV    "/sys/bus/usb/devices"
#define DEV_DISK_BY    "/dev/disk/by"
#define SYSFS_IDVENDOR    "idVendor"
#define SYSFS_IDPRODUCT    "idProduct"
#define SYSFS_BMAXPOWER    "bMaxPower"
#define SYSFS_MANUFACTURER  "manufacturer"
#define SYSFS_PRODUCT    "product"
#define SYSFS_FCHOST    "/sys/class/fc_host"

#define PRE  ""
#define PROC    "/proc"

#define PID_STAT  PRE "/proc/%u/stat"
#define PID_STATUS  PRE "/proc/%u/status"
#define PID_IO    PRE "/proc/%u/io"
#define PID_CMDLINE  PRE "/proc/%u/cmdline"
#define PID_SMAP  PRE "/proc/%u/smaps"
#define PID_FD    PRE "/proc/%u/fd"
#define PID_SCHED  PRE "/proc/%u/schedstat"

#define PROC_TASK  PRE "/proc/%u/task"
#define TASK_STAT  PRE "/proc/%u/task/%u/stat"
#define TASK_SCHED  PRE "/proc/%u/task/%u/schedstat"
#define TASK_STATUS  PRE "/proc/%u/task/%u/status"
#define TASK_IO    PRE "/proc/%u/task/%u/io"
#define TASK_CMDLINE  PRE "/proc/%u/task/%u/cmdline"
#define TASK_SMAP  PRE "/proc/%u/task/%u/smaps"
#define TASK_FD    PRE "/proc/%u/task/%u/fd"

#define F_NO_PID_IO  0x01
#define NO_PID_IO(m)    (((m) & F_NO_PID_IO) == F_NO_PID_IO)

/* Define SP_VALUE() to normalize to % */
#define SP_VALUE(m,n,p)    (((double) ((n) - (m))) / (p) * 100.0)
#define S_VALUE(m,n,p)    (((double) ((n) - (m))) / (p) * 100.0)

struct pid_stats {
  uint64_t read_bytes      __attribute__ ((aligned (8)));
  uint64_t write_bytes      __attribute__ ((packed));
  uint64_t cancelled_write_bytes  __attribute__ ((packed));
  uint64_t utime      __attribute__ ((packed));
  uint64_t stime      __attribute__ ((packed));
  uint64_t gtime      __attribute__ ((packed));
  uint64_t wtime      __attribute__ ((packed));
  unsigned long      nvcsw      __attribute__ ((packed));
  unsigned long      nivcsw      __attribute__ ((packed));
  uint32_t       threads      __attribute__ ((packed));
  uint32_t       fd_nr      __attribute__ ((packed));
};

struct ProgramState {
  std::string name;          // 程序名字
  pid_t pid;                 // 程序的 pid
  double cpu;                // 程序 cpu 使用占比
  double user_cpu;           // 程序 用户态cpu 使用占比
  double system_cpu;         // 程序 内核态cpu 使用占比
  uint32_t total_memory;     // 程序总内存
  uint32_t physical_memory;  // 程序使用物理内存
  uint32_t shared_memory;    // 程序使用共享内存
  uint32_t thread_num;       // 线程数
  double nvcsw;              // 程序自愿上下文切换
  double nivcsw ;            // 程序非自愿上下文切换
  double rbytes;             // 进程IO读速度KB/S
  double wbytes;             // 进程IO写速度KB/S
  double cbytes;             // 进程写入磁盘被取消的数据大小速度KB/S
};

#define PID_STATS_SIZE  (sizeof(struct pid_stats))

struct st_pid {
  pid_t       pid;
  uid_t       uid;  
  bool       exist = false;  /* TRUE if PID exists */
  uint32_t     flags = 0;
  std::unique_ptr<pid_stats> pstats[2];
  pid_t tgid;

  std::map<pid_t,st_pid> sub_thread_map;
  std::string name;
};

struct MemoryInformation {
    unsigned long total_memory;
    unsigned long physical_memory;
    unsigned long shared_memory;
};

class Common {
public:
  #define MAX_NAME_LEN    128
  #define KB_TO_PG(k)  ((k) >> Common::kb_shift)
  #define PG_TO_KB(k)  ((k) << Common::kb_shift)

  static void read_uptime(uint64_t *uptime);
  static void get_kb_shift(void);
  static void get_HZ(void);
  static uint64_t get_interval(uint64_t prev_uptime,
                                         uint64_t curr_uptime);

  static void add(pid_stats* a,pid_stats* b);
  static void get_st_pid(st_pid* a,const st_pid* b);
  static void get_st_pid(st_pid* a,int32_t a_idx,const st_pid* b,int32_t b_idx);
  static void display_info(struct st_pid *plist,int prev, int curr,uint64_t itv);
  static ProgramState get_program_state(st_pid *plist,
                                                          int prev, 
                                                          int curr,
                                                          uint64_t itv);
  static void get_cpu_num(void);                                                        
public:
  static inline uint32_t kb_shift;
  static inline unsigned long SYS_HZ;
  static inline unsigned long page_size;
  static inline uint32_t sys_cpu_num = 4;
};

}  // namespace deamon
}  // namespace xos
}  // namespace xag

#endif
